home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 9 / The PC-SIG Library on CD ROM - Ninth Edition.iso / 401_500 / DISK0426 / DISK0426.ZIP / GRAPH.PAS < prev    next >
Pascal/Delphi Source File  |  1985-02-25  |  27KB  |  706 lines

  1.  
  2.  
  3.  
  4. (*************************************************************
  5. **                                                          **
  6. **                 ICS 4390 Project                         **
  7. **                      part 2                              **
  8. **                   written by:                            **
  9. **                 Fereydon Shenassa                        **
  10. **                 Fall Quarter 1984                        **
  11. **                                                          **
  12. **  this program is a monitor which allows the use and test **
  13. **  of a 2d graphics package on a predefine object.         **
  14. **  the object is defined as a triangle with vertices at    **
  15. **  (-1,-1),(1,-1),(0,5) in world coordinates with a line   **
  16. **  in the middle (0,-1)-(0,5).                             **
  17. **                                                          **
  18. **  the operations defined are:                             **
  19. **    1)rotation,translation,scaling                        **
  20. **    2)window and viewport operations                      **
  21. **                                                          **
  22. **  the program makes use of 3 procedures in the lida       **
  23. **  package:                                                **
  24. **    1) openwk : initialize the workstation                **
  25. **    2) clearscreen                                        **
  26. **    3) line(x1,y1,x2,y2)                                  **
  27. **                                                          **
  28. **  the program is device independent.                      **
  29. *************************************************************)
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40. program monitor(input,output);
  41. (*************************************************************
  42. **  constants:                                              **
  43. **      userdimension- the number of dimensions the user    **
  44. **                     works with. 2 for this program.      **
  45. **      dimension    - userdimension + 1.                   **
  46. **      numhplanes   - number of hyperplanes in the viewport**
  47. **                     used in clipping                     **
  48. **                                                          **
  49. *************************************************************)
  50.  
  51. const
  52.    userdimension = 2;
  53.    dimension     = 3;
  54.    num_hplanes   = 4;
  55.  
  56.  
  57. (*************************************************************
  58. **  types:                                                  **
  59. **   elementtype : type of each entry in vectors and matrix **
  60. **   columntype  : one column of elements                   **
  61. **   matrixtype  : a matrix with 1 dimension higher than    **
  62. **                 the user dimension                       **
  63. **   pointype,vectortype : same as columntype, renamed for  **
  64. **                         clarity                          **
  65. **   viewareatype: array of halfspaces for clipping         **
  66. **   polygontyp  : polygon represented as circular          **
  67. **                 linked list                              **
  68. **   command     : a linked list representation of commands **
  69. **                 which could be lines or polygons         **
  70. **                                                          **
  71. *************************************************************)
  72.  
  73.  
  74. type
  75.   (*  types needed by the user to access package utilities *)
  76.  
  77.   devicechoice = (hp9845,iklores,ikhires, ps300,tek4115,tek4107);
  78.   inpnames     = (lightpen, digitizer, tablet);
  79.   inpclass     = (locator, pick, choice, valuator, strings, stroke);
  80.   outnames     = (plotter);
  81.   polygontype  = (hollow, solid);
  82.   pointcoords = record
  83.                 x, y : integer
  84.                 end;
  85.   symbolid = array[1..6] of char;
  86.   textstring  = array[1..80] of char;
  87.   ptpairarray = array[1..50] of pointcoords;
  88.   polytype    = array[0..49, 1..3] of integer;  (* for solid polygons *)
  89.   orientationrange = -180..180;   (* angle of the text *)
  90.   anglerange  = -89..89;          (* angle of each character in the text *)
  91.  
  92.  
  93.   colorrec   =    record
  94.                 hpred, hpgreen, hpblue : real
  95.                 end;
  96.  
  97.   (* types needed for the clipping operation *)
  98.  
  99.   realptcoords = record
  100.                   x, y : real;
  101.                   end;
  102.   
  103.   bezierarray = array[1..4] of realptcoords;
  104.  
  105.   lines = record
  106.           a, b, c : integer;  (* equation ax + by = c is used *)
  107.           orgdir : boolean;   (* true implies that the origin is outside *)
  108.           end;
  109.  
  110.   (* types needed by the package to process symbols  *)
  111.   commandptr   = ^commandentry;
  112.   commandentry = record
  113.                 next : commandptr;
  114.                 case tag: char of
  115.                  'a' : (polnum : integer;
  116.                         polptarr : ptpairarray);
  117.  
  118.                  'b' : (linnum : integer;
  119.                         linptarr : ptpairarray);
  120.  
  121.                  'c' : ();
  122.  
  123.                  'd' : (xs, ys, xd, yd : integer);     (* line *)
  124.  
  125.                  'e' : (setindex : integer; sred, sgreen, sblue : real);
  126.  
  127.                  'g' : (xt, yt, lgth : integer;
  128.                         strings : textstring);
  129.  
  130.                  'h' : (bezierpts : bezierarray);
  131.  
  132.                  'i' : (isymname : symbolid;
  133.                         i11, i12, i21, i22, i31, i32 : real);
  134.  
  135.                  'j' : (orientation : orientationrange);
  136.  
  137.                  'k' : (csize: integer; htwdthratio: real; tilt: anglerange);
  138.  
  139.                  'l' : (lstyle, lindex : integer );
  140.  
  141.                  'p' : (pfill : polygontype; pindex : integer);
  142.  
  143.                 end;
  144.  
  145.   symbolptr = ^symbolrec;
  146.   symbolrec = record
  147.                 name : array[1..6] of char;
  148.                 start : commandptr;
  149.                 next : symbolptr
  150.                end;
  151.  
  152.   segtransform = array [1..3,1..2] of real;
  153.  
  154.   visibility = (visible,invisible);
  155.  
  156.   highlighting = (normal,highlighted);
  157.  
  158.   detectability = (detectable,undetectable);
  159.  
  160.    elementtype   = real;
  161.    columntype    = array[1..dimension] of elementtype;
  162.    matrixtype    = array[1..dimension] of columntype;
  163.    pointtype     = columntype;
  164.    vectortype    = columntype;
  165.    segmenttype   = array[1..2] of pointtype;
  166.  
  167.    viewareatype  = array[1..num_hplanes] of lines;
  168.    polygontyp    = ^polygonelement;
  169.    polygonelement= record
  170.                    point: pointtype;
  171.                    next : polygontyp;
  172.                    end; { polygon element }
  173.  
  174.  
  175.    kindtype     = ( lineseg,poly);
  176.    command      = ^commandnode;
  177.    commandnode  = record
  178.                   next : command;
  179.                   case kind  : kindtype of
  180.                      lineseg : ( segment : segmenttype);
  181.                      poly    : ( polygon : polygontyp );
  182.                   end; { record }
  183.  
  184. (*************************************************************
  185. **  variables:                                              **
  186. **    mysymbol - predefined symbol used for testing the     **
  187. **               routines. a triangle with a line in middle **
  188. **    myviewarea-array of halfspaces defining the viewport  **
  189. **    transmatrix-global transformation matrix              **
  190. **    vindowmatrix-global viewing transformtion matrix      **
  191. **    x,ywindpos-location of left hand corner of window     **
  192. **    printmode - toggle for print routines on /off         **
  193. **                                                          **
  194. **    x,yscreensize-resolution of device in x and y direct  **
  195. **    viewminx,maxx-location of viewport in physical coord  **
  196. **    x,yscreensize-size of window in x and y directions    **
  197. **                                                          **
  198. *************************************************************)
  199.  
  200.  
  201. var
  202.   (* global variables needed by the package  *)
  203.   rs : char;    (* control character to indicate graphics command for HP Emul *)
  204.   station : devicechoice;
  205.   fill : boolean;
  206.   hpout : file of char;
  207.   psratio : real;
  208.   hpratio : real;      (* actually a constant of 4.55 *)
  209.   setfill : boolean;
  210.   esc,us : char; (*special chars for command initiation and termination
  211.                    on tek4115 and tek4107 *)
  212.   polyfillcolor : integer;   (* index location of fill color *)
  213.   lowres : boolean;
  214.   warnswitch : boolean;
  215.  
  216.   hptable : array[0..7] of colorrec;
  217.   hplinestyletab : array[0..9] of integer;
  218. (* variables needed to handle the window to viewport mapping *)
  219.   mapmode : boolean;
  220.   maphold : boolean;
  221.   maxscreensize : integer;
  222.   xscreensize, yscreensize : integer;
  223.   xwindsize, ywindsize : integer;
  224.   viewminx, viewmaxx : integer;
  225.   viewminy, viewmaxy : integer;
  226.   m11, m12, m21, m22, m31, m32 : real;   (* for the mapping transform *)
  227.   charsize : integer;
  228.   aspect : real;
  229.  
  230.   viewarea : array[1..4] of lines;       (* for the clipping operation *)
  231.   intersectcoords : pointcoords;
  232.  
  233.   z11, z12, z21, z22, z31, z32 : real;
  234.   recursecount : integer;
  235.  
  236. (* variables needed to handle the symbol mechanism *)
  237.   namecount : integer;   (* global count of number of names used for PS 300 *)
  238.   psname    : symbolid;
  239.   defmode : boolean;  (* boolean for definition mode command *)
  240.   symstart : symbolptr;
  241.   thiscommand : commandptr;
  242.   nextcommand : commandptr;
  243.   lastcommand : commandptr;
  244.  
  245.    mysymbol      : command;
  246.    myviewarea    : viewareatype;
  247.    transmatrix ,
  248.    windowmatrix  : matrixtype;
  249.    xwindpos,
  250.    ywindpos      : integer;
  251.    printmode     : boolean;
  252.  
  253.  
  254.  
  255.  
  256. (************************************************************
  257. **             initialization procedures                   **
  258. *************************************************************)
  259.  
  260. procedure initialize ;
  261. (*************************************************************
  262. **   initialize :                                           **
  263. **      open the work station as a tektronix 4107           **
  264. **      and clear the screen.                               **
  265. **      it sets up the xscreensize and yscreensize          **
  266. **                                                          **
  267. *************************************************************)
  268.  
  269.    begin { initialize}
  270. {   open_wk(tek4107);
  271.    clear_screen;}
  272.    end; {initialize}
  273.  
  274. procedure line(x1,y1,x2,y2 : integer );
  275.    begin
  276.    draw(x1,yscreensize-y1,x2,yscreensize-y2,white);
  277.    end; (* line *)
  278.  
  279.  
  280. procedure setidentity(  var matrix : matrixtype);
  281. (*************************************************************
  282. **  setidentity:                                            **
  283. **    reset the given matrix to the identity matrix         **
  284. **    with 1's in the diagonal and 0's elsewhere            **
  285. **                                                          **
  286. **  local variables:                                        **
  287. **    i,j : counters                                        **
  288. **                                                          **
  289. *************************************************************)
  290.    var
  291.      i,j : integer;
  292.  
  293.    begin { setidentity }
  294.    for i:= 1 to dimension do
  295.       begin
  296.       for j := 1 to dimension do
  297.          matrix[i,j] := 0;
  298.       matrix[i,i] := 1;
  299.       end;
  300.    end; { setidentity }
  301.  
  302.  
  303.  
  304. procedure define_model(var mysymbol     : command );
  305. (*************************************************************
  306. **  define_model:                                           **
  307. **    define the triangle used in the drawing routines      **
  308. **    using a polygon and a line.                           **
  309. **                                                          **
  310. **  local variables:                                        **
  311. **    element,element2 : pointers to polygon nodes          **
  312. **    command2         : pointer to the line node           **
  313. **                                                          **
  314. *************************************************************)
  315.  
  316.    var
  317.      element : polygontyp;
  318.      element2: polygontyp;
  319.      command2: command;
  320.    begin
  321.    new(mysymbol);
  322.    mysymbol^.next := nil;
  323.    mysymbol^.kind := poly;
  324.    with mysymbol^  do
  325.       begin
  326.       new(polygon);
  327.       new(element);
  328.       with polygon^ do
  329.          begin { with polygon }
  330.          point[1] := -3;
  331.          point[2] := -3;
  332.          point[3] := 1;
  333.          next := element;
  334.          end; { with polygon }
  335.       element^.point[1]:= 3;
  336.       element^.point[2]:= -3 ;
  337.       element^.point[3] := 1;
  338.       new(element2);
  339.       element^.next := element2;
  340.       element2^.next := polygon;
  341.       element2^.point[1] := 0;
  342.       element2^.point[2] := 3;
  343.       element2^.point[3] := 1;
  344.       end; { with }
  345.    new(command2);
  346.    command2^.next := nil;
  347.    command2^.kind := lineseg;
  348.    command2^.segment[1,1] := 0;
  349.    command2^.segment[1,2] := -3;
  350.    command2^.segment[2,1] := 0;
  351.    command2^.segment[2,2] := 3;
  352.    mysymbol^.next := command2;
  353.    end;   {define_symbol }
  354.  
  355. (************************************************************
  356. **                 read and print routines                 **
  357. *************************************************************)
  358.  
  359. procedure print(matrix : matrixtype);
  360. (*************************************************************
  361. **   print:                                                 **
  362. **     utility to print a square matrix of size dimension   **
  363. **     checks the printmode toggle first. if its false      **
  364. **     it doesn't print anything                            **
  365. **                                                          **
  366. **   local variables:                                       **
  367. **     i,j : counters                                       **
  368. **                                                          **
  369. *************************************************************)
  370.  
  371.    var
  372.       i , j : integer;
  373.    begin
  374.    if printmode then
  375.    begin
  376.    writeln;
  377.    write(' ':2);
  378.    for i:= 1 to dimension do
  379.       write('*******');
  380.    writeln('*');
  381.    for i := 1 to dimension do
  382.       begin
  383.       write('*':3);
  384.       for j := 1 to dimension do
  385.          write(matrix[i,j]:6:2);
  386.       writeln('*':3);
  387.       end; { i }
  388.    write(' ':2);
  389.    for i:= 1 to dimension do
  390.       write('*******');
  391.    writeln('*');
  392.    writeln;
  393.    end;
  394.    end; { print }
  395.  
  396. procedure  readvector(var  vector : vectortype );
  397. (*************************************************************
  398. **  readvector:                                             **
  399. **    read from the input elements of a vector of size      **
  400. **    userdimension.                                        **
  401. **                                                          **
  402. *************************************************************)
  403.  
  404.    var
  405.      i : integer;
  406.  
  407.    begin  { readvector }
  408.    for i := 1 to userdimension do
  409.       begin
  410.       write(i:1,'''th  element ? ');
  411.       readln(vector[i]);
  412.       vector[dimension] := 1;
  413.       end;
  414.    end; { readvector }
  415.  
  416.  
  417. (************************************************************
  418. **                 clipping algorithm                      **
  419. *************************************************************)
  420.  
  421.  
  422. procedure clip_line(    line     : segmenttype ;
  423.                     var result   : segmenttype;
  424.                         viewarea : viewareatype;
  425.                     var outside  : boolean );
  426. (*************************************************************
  427. **  clip_line :                                             **
  428. **     clip the given line segment to the viewarea given.   **
  429. **     and return the result. set outside to true if the    **
  430. **     line is completely outside the viewarea.             **
  431. **                                                          **
  432. **  local variables:                                        **
  433. **     i    : counter                                       **
  434. **     done : flag to tell end of clipping                  **
  435. **     outcode: array of boolean used to keep the           **
  436. **              location of each point with respect to      **
  437. **              the viewarea array.                         **
  438. **                                                          **
  439. **   local procedures:                                      **
  440. **     computelocation:return true if point is outside      **
  441. **                      the given halfspace                 **
  442. **     computeintersection: compute the intersection of a   **
  443. **                     point and a halfspace                **
  444. **                                                          **
  445. *************************************************************)
  446.  
  447.    var
  448.       i        : integer;
  449.       done     : boolean;
  450.       outcode  : array[1..num_hplanes,1..3] of boolean;
  451.  
  452.    function compute_location(point : pointtype ; line : lines): boolean;
  453.    (************************************************************
  454.    ** compute_location:                                       **
  455.    **    compute the location of the given point with         **
  456.    **    respect to the given line. return true if the        **
  457.    **    point is outside. false otherwise.                   **
  458.    **                                                         **
  459.    ** local variables:                                        **
  460.    **    result : temporary storage of the result of puting   **
  461.    **             the given point in the equation of the line **
  462.    **                                                         **
  463.    *************************************************************)
  464.  
  465.       var
  466.         result : real;
  467.  
  468.       begin  { compute_location }
  469.       with line do
  470.         begin
  471.         result := a * point[1] + b * point[2] ;
  472.          compute_location := not(  ( ( result < c ) and (not orgdir ) )
  473.                                  or( ( result > c ) and (    orgdir ) )
  474.                                  or(   result = c )
  475.                                    );
  476.         end;
  477.       end; { compute_location }
  478.  
  479.    procedure compute_intersection(var segment      : segmenttype ;
  480.                                       line         : lines ;
  481.                                       outsidepoint : integer );
  482.    (************************************************************
  483.    **  compute_intersection:                                  **
  484.    **     compute the intersection of the segment with the    **
  485.    **     given line. replace the result in the outside       **
  486.    **     endpoint. use the equation                          **
  487.    **        y = y1 + slope *(x-x1)                           **
  488.    **        x = x1 + 1/slope * (y-y1)                        **
  489.    **                                                         **
  490.    **  local variables:                                       **
  491.    **    tempx,tempy : temporary intersection points          **
  492.    **                                                         **
  493.    *************************************************************)
  494.  
  495.       var
  496.          tempx , tempy   : real;
  497.  
  498.       begin  { compute_intersection }
  499.       with line do
  500.       if (line.a = 0 ) then
  501.          begin
  502.          if (segment[2,2] - segment[1,2]) <> 0 then
  503.          begin
  504.          tempx := segment[1,1] + (segment[2,1] - segment[1,1])
  505.                                * (line.c - segment[1,2]      )
  506.                               / ( segment[2,2] - segment[1,2]);
  507.          tempy := line.c;
  508.          end
  509.          else
  510.            begin
  511.          tempx := segment[1,1];
  512.          tempy := line.c;
  513.            end;
  514.          end
  515.       else
  516.          begin
  517.          if (segment[2,1] - segment[1,1]) <> 0 then
  518.          begin
  519.          tempy := segment[1,2] + (segment[2,2] - segment[1,2])
  520.                                * (line.c - segment[1,1]      )
  521.                              / ( segment[2,1] - segment[1,1]);
  522.          tempx := line.c;
  523.          end
  524.          else
  525.             begin
  526.          tempy := segment[1,2] ;
  527.          tempx := line.c;
  528.             end
  529.          end;
  530.       segment[outsidepoint,1] := trunc(tempx);
  531.       segment[outsidepoint,2] := trunc(tempy);
  532.  
  533.      end; { compute_intersection }
  534.  
  535.    (************************************************************
  536.    **            body of clip line starts here                **
  537.    *************************************************************)
  538.  
  539.    begin { body of clip_line }
  540.    done    := false;
  541.    i       := 1;
  542.    outside := false;
  543.    result  := line;
  544.    while (not done ) and ( i <= num_hplanes) do
  545.       begin
  546.       outcode[i,1] := compute_location(line[1],viewarea[i]);
  547.       outcode[i,2] := compute_location(line[2],viewarea[i]);
  548.  
  549.       if outcode[i,1] and outcode[i,2] then
  550.           begin
  551.           outside := true;
  552.           done    := true;
  553.           end
  554.       else
  555.           outcode[i,3] := (not outcode[i,1]) and (not outcode[i,2]);
  556.           { if both points are inside, skip that hplane, later }
  557.       i := i + 1;
  558.       end; { while }
  559.  
  560.    if ( not done ) then
  561.       begin
  562.       i := 1;
  563.       while (i <=num_hplanes ) and (not done)  do
  564.          begin
  565.          if (not outcode[i,3]) then
  566.             begin
  567.             outcode[i,1] := compute_location(result[1],viewarea[i]);
  568.             outcode[i,2] := compute_location(result[2],viewarea[i]);
  569.  
  570.             if (outcode[i,1] and outcode[i,2] ) then
  571.                begin
  572.                done    := true;
  573.                outside := true;
  574.                end
  575.             else
  576.                begin
  577.                if outcode[i,1] or outcode[i,2] then
  578.                   if ( outcode[i,1] ) then
  579.                      compute_intersection(result,viewarea[i],1)
  580.                   else
  581.                      compute_intersection(result,viewarea[i],2);
  582.                end;
  583.             end;
  584.          i := i + 1;
  585.          end; { while not done }
  586.       end; { if not done }
  587.    end; { clip_line }
  588.  
  589. (************************************************************
  590. **             matrix operation routines                   **
  591. *************************************************************)
  592.  
  593.  
  594.  
  595. procedure  concatenate(leftmatrix,rightmatrix : matrixtype;
  596.                              var   resultmatrix: matrixtype);
  597. (************************************************************
  598. **   concatenate:                                          **
  599. **     multiply the left and right matrices and put the    **
  600. **     result in resultmatrix.                             **
  601. **                                                         **
  602. **   local variables:                                      **
  603. **     i,j,k : counters                                    **
  604. **     temp  : temporary storage area for sum of a column  **
  605. **                                                         **
  606. *************************************************************)
  607.  
  608.  
  609.   var
  610.      i,j,k : integer;
  611.      temp  : elementtype;
  612.  
  613.   begin { concatenate }
  614.   for i := 1 to dimension do
  615.      begin
  616.      for j := 1 to dimension do
  617.         begin
  618.         temp := 0;
  619.         for k  := 1 to dimension do
  620.            temp := temp + leftmatrix[i,k] * rightmatrix[k,j] ;
  621.         resultmatrix[i,j] := temp ;
  622.         end;
  623.      end;
  624.   end; { concatenate }
  625.  
  626. procedure applymatrix(var segment : segmenttype;
  627.                           matrix  : matrixtype );
  628. (************************************************************
  629. **  applymatrix:                                           **
  630. **    multiply the segment vector by the matrix and return **
  631. **    the result in the segment.                           **
  632. **                                                         **
  633. **  local variables:                                       **
  634. **    i : counter                                          **
  635. **    tempseg: temporary result of multiplication.         **
  636. **                                                         **
  637. *************************************************************)
  638.  
  639.    var
  640.       i         : integer;
  641.       tempseg   : segmenttype;
  642.  
  643.    begin { applymatrix }
  644.    for i := 1 to 2 do
  645.       begin
  646.       tempseg[i,1] := segment[i,1] * matrix[1,1]+
  647.                       segment[i,2] * matrix[2,1]+
  648.                                    + matrix[3,1];
  649.       tempseg[i,2] := segment[i,1] * matrix[1,2]+
  650.                       segment[i,2] * matrix[2,2]+
  651.                                    + matrix[3,2];
  652.       tempseg[i,3] := 1;
  653.       end; { for }
  654.    segment := tempseg;
  655.    end; {applymatrix }
  656.  
  657.  
  658.  
  659. (************************************************************
  660. **             transformation routines                     **
  661. *************************************************************)
  662.  
  663.  
  664. procedure translate(var inputmatrix :matrixtype;
  665.                          transvector : vectortype );
  666. (************************************************************
  667. **  translate:                                             **
  668. **     add a translation by a translation vector to the    **
  669. **     inputmatrix.                                        **
  670. **                                                         **
  671. **  local variables:                                       **
  672. **     i : counters                                        **
  673. **                                                         **
  674. *************************************************************)
  675.  
  676.    var
  677.      i  : integer;
  678.    begin  { translate}
  679.    for i := 1 to userdimension do
  680.       inputmatrix[dimension,i] := inputmatrix[dimension,i]
  681.                                  +transvector[i];
  682.    end; { translate }
  683.  
  684.  
  685. procedure scale(var inputmatrix  : matrixtype ;
  686.                     scalevector  : vectortype );
  687. (************************************************************
  688. **  scale:                                                 **
  689. **    concatenate a scaling matrix of value scalevector    **
  690. **    to the input matrix.  the procedure is optimized     **
  691. **                                                         **
  692. **  local variables:                                       **
  693. **    i,j : counters                                       **
  694. **                                                         **
  695. *************************************************************)
  696.  
  697.    var
  698.    i , j : integer;
  699.    begin  { scale }
  700.    for i := 1 to userdimension do
  701.       for j := 1 to dimension do
  702.          inputmatrix[j,i]  := inputmatrix[j,i] * scalevector[i] ;
  703.    end; { scale }
  704. {$i graph2.pas }
  705.  := 1 to dimension do
  706.          inputmatrix[j,i]  := inputmatrix[j,i] * scalevector